package xyz.icxl.android.architecture.data.net.okhttp.body

import okhttp3.MediaType
import okhttp3.RequestBody
import okio.*
import xyz.icxl.android.architecture.data.net.okhttp.ProgressListener

/**
 * 文件描述：文件上传进度监听Body
 *          在Sink.write()中监听上传进度
 *
 * 文件创建人：ChenXinLei
 *
 * 文件创建人联系方式：502616659(QQ)
 *
 * 创建时间：2020 年 08月 25 日
 *
 * 文件版本：v1.0
 *
 * 版本描述：创建文件
 *
 * 如何使用：
 * ```kotlin
 *     val file = File(path)
 *     val fileBody = RequestBody.create(MediaType.parse("multipart/form-data"), file)
 *     //最终要post的requestBody
 *     val requestBody = ProgressResponseForUploadBody(fileBody) { progress ->
 *       //利用progress值更新UI或处理其它业务逻辑
 *     }
 * ```
 */
class ProgressResponseForUploadBody(
    private val requestBody: RequestBody,
    private val progressListener: ProgressListener? = null
): RequestBody() {

    private lateinit var bufferedSink: BufferedSink

    override fun contentType(): MediaType? = requestBody.contentType()

    override fun contentLength(): Long = requestBody.contentLength()

    override fun writeTo(sink: BufferedSink) {
        if (!this::bufferedSink.isInitialized)
            bufferedSink = getWrappedSink(sink).buffer()
        requestBody.writeTo(bufferedSink)
        bufferedSink.flush()
    }

    private fun getWrappedSink(sink: Sink): Sink = object : ForwardingSink(sink) {

        private var bytesWritten = 0L
        private val contentLength by lazy {
            contentLength()
        }

        override fun write(source: Buffer, byteCount: Long) {
            super.write(source, byteCount)
            bytesWritten += byteCount
            val progress = (bytesWritten / contentLength.toFloat())*100
            progressListener?.invoke(progress.toInt())
        }
    }
}
